package player

import (
	"GameServer/Common/utils"
	"fmt"
	"time"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"

	"GameServer/Common/data"
	"GameServer/Game/activity"
	"GameServer/Game/errors"
	"GameServer/Game/jackpot"
	"GameServer/Game/lib"
	"GameServer/Game/m"
	"GameServer/Game/plog"
	"GameServer/Game/slot_fire"
	"GameServer/Game/slot_steal"
	"GameServer/Game/sp"
	"GameServer/Game/union"
)

func (p *Player) SlotRewardRequest(req *sp.SlotRewardRequest) (res *sp.SlotRewardResponse, err error) {
	us := p.User

	if v, ok := p.GetData("slotLimitTime"); ok {
		if utils.TNow().Unix() < v.(int64) {
			log.WithFields(log.Fields{
				"uid":    us.Uid.Hex(),
				"method": "SlotRewardRequest",
			}).Debug("老虎机点击速度过快")
			res = &sp.SlotRewardResponse{
				Errcode: data.Errcode.ServerErr,
			}
			return
		}
	}

	var gmKey uint64 = 0
	if v, ok := p.GetData("slotKeyGm"); ok {
		gmKey = v.(uint64)
	}

	var isNewGuideSlot bool = false
	if v, ok := p.GetData("newGuildslotKey"); ok {
		gmKey = v.(uint64)
		isNewGuideSlot = true
		p.DeleteData("newGuildslotKey")
	}

	if v, ok := lib.TargetAssignment(p.User); ok { // 三次指定事件
		gmKey = v
	}
	// 新手引导
	// isNewGuideSlot, key, uProp, resGoodsList, err := lib.NewGuidSlotGuid("SlotRewardRequest", p.User, req.Spin, p.Send)
	// if err != nil {
	// 	res = &sp.SlotRewardResponse{
	// 		Errcode: errors.ErrCode(err),
	// 	}
	// 	return
	// }
	// 不是新手引导
	// if !isNewGuideSlot {
	key, uProp, resGoodsList, err := lib.SlotReward("SlotRewardRequest", p.User, req.Spin, gmKey, p.Send)
	if err != nil {
		res = &sp.SlotRewardResponse{
			Errcode: errors.ErrCode(err),
		}
		return
	}
	// 有成就完成，进行通知
	achLst := lib.AchievComplete(p.User)
	if len(achLst) > 0 {
		p.Send(&sp.AchievementNoticeRequest{
			Lst: achLst,
		})
	}
	for _, item := range resGoodsList {
		if item.Tid == 220001 {
			jackpot.Module.IncrGoldSlotScale(item.Num)
		}
	}
	// }

	plog.Log_SlotLog(p.User, key, resGoodsList, uProp, req.Spin)
	// p.TimelyUpdateProp(req.GetType(), uProp)
	p.UpdateProp(req.GetType(), uProp)

	p.PutData("slotKey", key)
	p.PutData("slotLimitTime", utils.TNow().Unix()+1)
	p.PutData("slotSpin", req.Spin)

	res = &sp.SlotRewardResponse{
		Tid: key,
		Res: lib.FormatGoodsInfoSps(resGoodsList),
	}
	if isNewGuideSlot && p.User.MaxPos.LockBlockTid < 2 {
		res.HideShopFireNum = 0
	} else {
		realHideShopFireNum := p.User.HideShop().AddFireNum(key)
		res.HideShopFireNum = realHideShopFireNum
	}

	if key == 777 {
		if activity.ActivityModule.HasSlotAct() {
			// 触发3个相同活动道具事件
			p.SlotActActionOccur(data.SlotActActionEnum.TrebleSp, req.Spin)
		}
	}
	return
}

// 偷盗，进入偷盗事件申请
func (p *Player) SlotTheftReqRequest(req *sp.SlotTheftReqRequest) (res *sp.SlotTheftReqResponse, err error) {
	us := p.User
	slotKey, ok := p.GetData("slotKey")
	if !ok {
		log.WithFields(log.Fields{
			"Uid":    us.Uid.Hex(),
			"Name":   us.Name,
			"method": "SlotTheftReqRequest",
		}).Error("没有获取到任何事件")
		res = &sp.SlotTheftReqResponse{
			Errcode: data.Errcode.ServerErr,
		}
		return
	}

	if slotKey.(int64) != 555 {
		log.WithFields(log.Fields{
			"Uid":     us.Uid.Hex(),
			"Name":    us.Name,
			"slotKey": slotKey,
			"method":  "SlotTheftReqRequest",
		}).Error("不是偷窃事件")
		res = &sp.SlotTheftReqResponse{
			Errcode: data.Errcode.ServerErr,
		}
		return
	}

	if us.UnionId != "" {
		spin, _ := p.GetData("slotSpin")
		uProp, _, _, err := lib.GiveGoodsByKv("SlotTheftReqRequest", us, m.BaseKV{Key: data.GlobalEnum.Union, Val: spin.(int64)}, p.Send)
		if err != nil {
			log.WithFields(log.Fields{
				"Uid":    us.Uid.Hex(),
				"Name":   us.Name,
				"data":   spin.(int64),
				"method": "SlotTheftReqRequest",
			}).Error("给公会积分失败")
		} else {
			p.TimelyUpdateProp(req.GetType(), uProp)
			utils.AsyncFunc(func() {
				p.UpdateProp(req.GetType(), uProp)
			})
		}
	}

	p.PutData("slotKey", int64(0))
	// 新手引导
	newGuildFlag := false
	uNewGuide := us.GetNewGuide()
	// 新手引导
	if !uNewGuide.SlotFlag && us.MaxPos.LockBlockTid == 1 {
		newGuildFlag = true
	}

	if v, ok := p.GetData("slotUser"); ok {
		tu, ok := p.getPlayer(v)
		p.PutData("tSlotUser", v) // 偷盗存入临时变量，防止大富豪玩家钱少于上线，更换大富豪，被偷日志和偷的大富豪不一样。
		if !ok {
			log.WithFields(log.Fields{
				"Uid":      us.Uid.Hex(),
				"Name":     us.Name,
				"slotUser": v,
				"method":   "SlotTheftReqRequest",
			}).Error("没有找到偷窃的玩家对象")
			res = &sp.SlotTheftReqResponse{
				Errcode: data.Errcode.ServerErr,
			}
			return
		}
		spUserInfo := lib.FormatSlotUser(us, tu.User, newGuildFlag)

		// 触发老虎机活动--偷盗行为
		if activity.ActivityModule.HasSlotAct() && newGuildFlag == false {
			spin, _ := p.GetData("slotSpin")
			p.SlotActActionOccur(data.SlotActActionEnum.Stole, spin.(int64))
		}

		goldNum, tGoldNum, boxGoods, petGoods, tuProp, err := lib.SlotTheftBoxs(us, tu.User)
		if err != nil {
			res = &sp.SlotTheftReqResponse{
				Errcode: errors.ErrCode(err),
			}
			return res, err
		}
		// 增加偷取次数
		us.GetUserStatic().AddTypNum(data.StaticTYP.Theft, 1)
		// 成就，记录劫掠偷盗次数。
		lib.AddAchievProgress(us, data.AchievementType.SlotGoblin, 1)
		// 有成就完成，进行通知
		achLst := lib.AchievComplete(us)
		if len(achLst) > 0 {
			p.Send(&sp.AchievementNoticeRequest{
				Lst: achLst,
			})
		}
		if !tu.User.Robot {
			plog.Log_BeTheft(tu.User, us.Uid.Hex(), tGoldNum)
			m.AddEventMsg(tu.User.Uid, &m.EventMsg{
				Id:          bson.NewObjectId().Hex(),
				Uid:         us.Uid.Hex(),
				Name:        us.Name,
				Head:        us.Head,
				Op:          1,
				Value:       tGoldNum,
				Time:        utils.TNow().Unix(),
				AvatarFrame: us.AvatarFrame,
			})
			if !tu.User.IsOffLine() {
				// 玩家在线
				utils.AsyncFunc(func() {
					tu.Send(&sp.SlotTheftNoticeRequest{
						Uid:         us.Uid.Hex(),
						Name:        us.Name,
						Tnum:        tGoldNum,
						Head:        us.Head,
						AvatarFrame: us.AvatarFrame,
					})
				})
			} else {

			}
			if tuProp != nil {
				tuProp.SetSlotNoticeSkip(true)
				tu.TimelyUpdateProp(req.GetType(), tuProp)
				utils.AsyncFunc(func() {
					tu.UpdateProp(req.GetType(), tuProp)
				})
			}
		}

		goldNum = 0 //不需要记录该值

		p.PutData("boxFlag", int64(1)<<5-1) // 未开的盒子，该数二进制的位置上为1，如果开了，置位0
		p.PutData("boxGoods", boxGoods)
		p.PutData("boxPetGoods", petGoods)
		p.PutData("slotNum", 0)
		p.PutData("slotGoldNum", goldNum)

		var layer *m.Layer
		if tu.User.Robot {
			val, _ := p.GetData("robotLayer")
			layer = val.(*m.Layer)
		} else {
			layer = lib.CurrentLayer(tu.User)
			slot_steal.AddStealProtec(tu.User.Uid.Hex(), utils.TNow().Add(5*time.Minute).Unix()) //被偷盗后，保护5分钟。
		}
		res = &sp.SlotTheftReqResponse{
			TheftInfo: &sp.SlotTheftInfo{
				UserInfo: spUserInfo,
				BoxIds:   []int64{1, 2, 3, 4},
				Layer:    lib.FormartLayerSp(layer),
			},
		}
		return res, nil
	}
	res = &sp.SlotTheftReqResponse{
		Errcode: data.Errcode.ServerErr,
	}
	return
}

// 偷盗，开启某个格子
func (p *Player) SlotTheftRequest(req *sp.SlotTheftRequest) (res *sp.SlotTheftResponse, err error) {
	us := p.User
	log.WithFields(log.Fields{
		"Uid":    us.Uid.Hex(),
		"Name":   us.Name,
		"BoxId":  req.BoxId,
		"method": "SlotTheftRequest",
	}).Debug("偷盗，请求开启箱子...")

	// 检查盒子是否已经开启
	boxFlag, ok := p.GetData("boxFlag")
	if !ok {
		return nil, errors.New("boxFlag not found")
	}
	boxFlagT := boxFlag.(int64)
	if boxFlagT&(1<<req.BoxId) <= 0 {
		res = &sp.SlotTheftResponse{} // 该盒子已经打开
		return
	}
	boxFlagT &= ^(1 << req.BoxId) // 将该盒子取消
	p.PutData("boxFlag", boxFlagT)

	// 盒子索引 slotNum=0,1,2,3
	vSlotNum, ok := p.GetData("slotNum")
	if !ok {
		return nil, errors.New("slotNum not found")
	}
	slotNum := vSlotNum.(int)
	// 获取盒子信息
	vBoxGoods, ok := p.GetData("boxGoods")
	if !ok {
		return nil, errors.New("boxGoods not found")
	}
	boxGoods := vBoxGoods.([]m.Goods)
	goods := boxGoods[slotNum]

	// 开启第3个箱子，刷新玩家的大富豪
	if slotNum == 2 {
		utils.AsyncFunc(func() {
			p.RefreshSlotUser()
		})
	}
	spin, _ := p.GetData("slotSpin")
	var petRateGoldNum int64 = 0
	// 请求第4个箱子时，是宠物偷盗。
	if slotNum == 3 {
		goldNumVal, _ := p.GetData("slotGoldNum")
		goldNum := goldNumVal.(int64) / spin.(int64)
		rateVal := p.User.GetUserPet().GetSkillVal(uint64(data.PetSkillEffectEnum.AddTheftGold))
		if rateVal > 0 {
			petRateGoldNum = int64(float64(goldNum) * (rateVal / float64(100)))
		}

		petGoods, _ := p.GetData("boxPetGoods")
		goods = petGoods.(m.Goods)
		goods.Num = petRateGoldNum //这里只是使用petGoods的物品ID而已

		fmt.Println("petSkill------> goldNumVal:", goldNumVal, "goldNum:", goldNum, "rateVal:", rateVal, "petRateGoldNum:", petRateGoldNum)
	}

	// 当金币数量为0，开启箱子，客户端显示空。
	if goods.Num == 0 {
		p.PutData("slotNum", slotNum+1)
		res = &sp.SlotTheftResponse{}
		return res, nil
	}

	rGoods, muProp, resGoodsList, err := lib.SlotTheft("SlotTheftRequest", p.User, goods, 0, spin.(int64), p.Send)
	if err != nil {
		res = &sp.SlotTheftResponse{
			Errcode: errors.ErrCode(err),
		}
		return res, err
	}

	newGuide := us.GetNewGuide()
	if !newGuide.SlotFlag && us.MaxPos.LockBlockTid == 1 {
		newGuide.RewardCnt++ // 记录偷盗次数
		newGuide.Update(newGuide)
	}

	// 有成就完成，进行通知
	achLst := lib.AchievComplete(p.User)
	if len(achLst) > 0 {
		p.Send(&sp.AchievementNoticeRequest{Lst: achLst})
	}

	tSlotUser, _ := p.GetData("tSlotUser")
	if tuPlayer, ok := p.getPlayer(tSlotUser); ok {
		plog.Log_Theft(p.User, tuPlayer.User, int64(slotNum), &rGoods, resGoodsList, muProp)
	}

	// 委托活动，玩家通过老虎机开启宝箱，非空记录一次。
	lib.CalcHonor(p.User, data.EntrType.Goblin, data.EntrEnum.StealUser, spin.(int64))
	if num := lib.EntrustCheck(p.User); num > 0 {
		utils.AsyncFunc(func() {
			p.Send(&sp.EntrustNoticeRequest{Num: num})
		})
	}
	p.PutData("boxGoods", boxGoods)
	p.PutData("slotNum", slotNum+1)

	goldNumVal, _ := p.GetData("slotGoldNum")
	goldNumVal = goldNumVal.(int64) + rGoods.Num
	p.PutData("slotGoldNum", goldNumVal)

	res = &sp.SlotTheftResponse{
		Reward:       &sp.Goods{Tid: rGoods.Tid, Num: rGoods.Num},
		ResList:      lib.FormatGoodsInfoSps(resGoodsList),
		PetSkillGold: petRateGoldNum,
	}

	p.TimelyUpdateProp(req.GetType(), muProp)
	utils.AsyncFunc(func() {
		p.UpdateProp(req.GetType(), muProp)
	})

	return res, nil
}

func (p *Player) SlotTheftEndRequest(req *sp.SlotTheftEndRequest) (res *sp.SlotTheftEndResponse) {
	res = &sp.SlotTheftEndResponse{}
	return
}

func (p *Player) SlotFireReqRequest(req *sp.SlotFireReqRequest) (res *sp.SlotFireReqResponse, err error) {
	// res = &sp.SlotFireReqResponse{
	// 	Errcode: data.Errcode.ServerErr,
	// }
	// slotKey, ok := p.GetData("slotKey")
	// if !ok {
	// 	res = &sp.SlotFireReqResponse{
	// 		Errcode: data.Errcode.ServerErr,
	// 	}
	// 	log.WithFields(log.Fields{
	// 		"uid":    p.User.Uid.Hex(),
	// 		"method": "SlotFireReqRequest",
	// 	}).Error("没有获取到任何事件")
	// 	return
	// }

	// if slotKey.(int64) != 666 {
	// 	res = &sp.SlotFireReqResponse{
	// 		Errcode: data.Errcode.ServerErr,
	// 	}
	// 	log.WithFields(log.Fields{
	// 		"data":   map[string]interface{}{"slotKey": slotKey},
	// 		"uid":    p.User.Uid.Hex(),
	// 		"method": "SlotFireReqRequest",
	// 	}).Error("不是放火事件")
	// 	return
	// }

	// p.PutData("slotFireEndTime", utils.TNow().Add(5*time.Minute).Unix())

	// // 新手引导
	// newGuildFlag := false

	// uNewGuide := p.User.GetNewGuide()
	// // 新手引导
	// if !uNewGuide.SlotFlag && p.User.MaxPos.LockBlockTid == 1 {
	// 	newGuildFlag = true
	// }

	// if req.Uid == "" {
	// 	// gm 设置的放火玩家
	// 	if v, ok := p.GetData("gmFireUser"); ok {
	// 		p.PutData("fireUser", v.(string))
	// 		tuPlayer, ok := p.getPlayer(v.(string))
	// 		if !ok {
	// 			log.WithFields(log.Fields{
	// 				"uid":    p.User.Uid.Hex(),
	// 				"method": "SlotFireReqRequest",
	// 			}).Error("没有找到被放火的玩家")
	// 			return res, nil
	// 		}
	// 		tuPlayer.User.FireIng()

	// 		// 增加放火次数
	// 		p.User.GetUserStatic().AddTypNum(data.StaticTYP.Fire, 1)
	// 		// 移除被保护
	// 		slot.RemoveProtec(p.User.Uid.Hex())
	// 		res = &sp.SlotFireReqResponse{
	// 			FireInfo: &sp.SlotFireInfo{
	// 				UserInfo: lib.FormatSlotUser(p.User, tuPlayer.User, newGuildFlag),
	// 				Layer:    lib.FormartLayerSp(tuPlayer.User.GetLayer()),
	// 				UserPet:  lib.FormatPetSp(tuPlayer.User.GetUserPet().GetActivePet()),
	// 			},
	// 		}
	// 		return res, nil
	// 	}
	// 	if v1, ok := p.GetData("newGuildFireShield"); ok {
	// 		isHaveShiled := v1.(int)

	// 		robot, _, robotLayer, err := lib.NewGuildRobot()
	// 		if err != nil {
	// 			return res, err
	// 		}
	// 		p.DeleteData("newGuildFireShield")
	// 		if isHaveShiled == 0 {
	// 			robot.Shield = 0
	// 		} else {
	// 			robot.Shield = 3
	// 		}
	// 		p.PutData("fireUser", robot)
	// 		p.PutData("robotLayer", robotLayer)
	// 		res = &sp.SlotFireReqResponse{
	// 			FireInfo: &sp.SlotFireInfo{
	// 				UserInfo: lib.FormatSlotUser(p.User, robot, newGuildFlag),
	// 				Layer:    lib.FormartLayerSp(robotLayer),
	// 			},
	// 		}
	// 		return res, nil
	// 	}
	// 	offlines := PlayersModule.Offlines()
	// 	rlist := slot.Filter(p.User.Uid.Hex(), offlines)
	// 	fireUser, _, robotLayer, err := lib.SlotFireMatchs(p.User.Pos.LockBlockTid, rlist)
	// 	if err != nil {
	// 		log.WithFields(log.Fields{
	// 			"uid":    p.User.Uid.Hex(),
	// 			"method": "SlotFireReqRequest",
	// 		}).Error("匹配放火玩家错误:", err)
	// 		return nil, err
	// 	}

	// 	if fireUser.Robot {
	// 		p.PutData("fireUser", fireUser)
	// 		p.PutData("robotLayer", robotLayer)
	// 	} else {
	// 		p.PutData("fireUser", fireUser.Uid.Hex())
	// 		fireUser.FireIng()
	// 	}

	// 	fireUserData, _ := p.GetData("fireUser")

	// 	tuPlayer, ok := p.getPlayer(fireUserData)
	// 	if !ok {
	// 		log.WithFields(log.Fields{
	// 			"uid":    p.User.Uid.Hex(),
	// 			"method": "SlotFireReqRequest",
	// 		}).Error("没有找到被放火的玩家")
	// 		return nil, nil
	// 	}
	// 	// 增加放火次数
	// 	p.User.GetUserStatic().AddTypNum(data.StaticTYP.Fire, 1)
	// 	// 移除被保护
	// 	slot.RemoveProtec(p.User.Uid.Hex())

	// 	var layer *m.Layer
	// 	var pet *m.Pet
	// 	if fireUser.Robot {
	// 		layer = robotLayer
	// 		pet = nil
	// 	} else {
	// 		layer = tuPlayer.User.GetLayer()
	// 		pet = tuPlayer.User.GetUserPet().GetActivePet()
	// 	}
	// 	res = &sp.SlotFireReqResponse{
	// 		FireInfo: &sp.SlotFireInfo{
	// 			UserInfo: lib.FormatSlotUser(p.User, tuPlayer.User, newGuildFlag),
	// 			Layer:    lib.FormartLayerSp(layer),
	// 			UserPet:  lib.FormatPetSp(pet),
	// 		},
	// 	}
	// 	return res, nil
	// }
	// // 选择复仇玩家
	// tuPlayer, ok := p.getPlayer(req.Uid)
	// if !ok {
	// 	log.WithFields(log.Fields{
	// 		"uid":    p.User.Uid.Hex(),
	// 		"method": "SlotFireReqRequest",
	// 		"data":   req,
	// 	}).Error("没有找到被放火的玩家")
	// 	res = &sp.SlotFireReqResponse{
	// 		Errcode: data.Errcode.ServerErr,
	// 	}
	// 	return res, nil
	// }
	// //更新被烧家ID
	// p.PutData("fireUser", req.Uid)
	// // 增加放火次数
	// p.User.GetUserStatic().AddTypNum(data.StaticTYP.Fire, 1)
	// // 移除被保护
	// slot.RemoveProtec(p.User.Uid.Hex())
	// res = &sp.SlotFireReqResponse{
	// 	FireInfo: &sp.SlotFireInfo{
	// 		UserInfo: lib.FormatSlotUser(p.User, tuPlayer.User, newGuildFlag),
	// 		Layer:    lib.FormartLayerSp(tuPlayer.User.GetLayer()),
	// 	},
	// }
	// res.FireInfo.UserPet = lib.FormatPetSp(tuPlayer.User.GetUserPet().GetActivePet())

	return
}

func (p *Player) SlotFireRequest(req *sp.SlotFireRequest) (res *sp.SlotFireResponse, err error) {

	// p.DeleteData("gmFireUser")
	// slotfireEndTime, ok := p.GetData("slotFireEndTime")
	// if !ok {
	// 	res = &sp.SlotFireResponse{
	// 		Errcode: data.Errcode.ServerErr,
	// 	}
	// 	log.WithFields(log.Fields{
	// 		"uid":    p.User.Uid.Hex(),
	// 		"method": "SlotFireRequest",
	// 	}).Error("没有获取到放火结束时间")
	// 	return
	// }

	// if v, ok := p.GetData("fireUser"); ok {
	// 	tuPlayer, ok := p.getPlayer(v)
	// 	if !ok {
	// 		res = &sp.SlotFireResponse{
	// 			Errcode: data.Errcode.ServerErr,
	// 		}
	// 		log.WithFields(log.Fields{
	// 			"uid":    p.User.Uid.Hex(),
	// 			"data":   map[string]interface{}{"fireUser": v},
	// 			"method": "SlotFireRequest",
	// 		}).Error("未获取到放火玩家")
	// 		return
	// 	}

	// 	tu := tuPlayer.User
	// 	if utils.TNow().Unix() > slotfireEndTime.(int64) {
	// 		log.WithFields(log.Fields{
	// 			"uid":    p.User.Uid.Hex(),
	// 			"data":   map[string]interface{}{"fireUser": v},
	// 			"method": "SlotFireRequest",
	// 		}).Debug("放火超时")
	// 		tu.UnFire()
	// 		res = &sp.SlotFireResponse{
	// 			Errcode: data.Errcode.FireTimeOut,
	// 		}
	// 		return res, nil
	// 	}
	// 	spin, _ := p.GetData("slotSpin")
	// 	var uProp *m.UpdateProp
	// 	var resGoods *m.Goods
	// 	var err error
	// 	if tu.Robot {
	// 		val, _ := p.GetData("robotLayer")
	// 		layer := val.(*m.Layer)
	// 		uProp, resGoods, err = lib.RobotSlotFire(p.User, tu, layer, req.GridIds, spin.(int64))
	// 	} else {
	// 		uProp, resGoods, err = lib.SlotFire(p.User, tu, req.GridIds, spin.(int64))
	// 	}

	// 	var errcode int64 = 0
	// 	var eventFireOp int64 = 2
	// 	if err != nil {
	// 		if errors.ErrCode(err) != data.Errcode.HasShield && errors.ErrCode(err) != data.Errcode.HasPetSkillShield {
	// 			res = &sp.SlotFireResponse{
	// 				Errcode: errors.ErrCode(err),
	// 			}
	// 			return res, err
	// 		}
	// 		if errors.ErrCode(err) == data.Errcode.HasShield {
	// 			errcode = data.Errcode.HasShield
	// 			eventFireOp = 3
	// 		}

	// 		if errors.ErrCode(err) == data.Errcode.HasPetSkillShield {
	// 			errcode = data.Errcode.HasPetSkillShield
	// 			eventFireOp = 4
	// 		}
	// 	}

	// 	if p.User.UnionId != "" {
	// 		uProp, _, _, err := lib.GiveGoodsByKv("SlotFireRequest", p.User, m.BaseKV{Key: data.GlobalEnum.Union, Val: 1 * spin.(int64)})
	// 		if err != nil {
	// 			log.WithFields(log.Fields{
	// 				"data":   m.BaseKV{Key: data.GlobalEnum.Union, Val: 1},
	// 				"uid":    p.User.Uid.Hex(),
	// 				"method": "SlotFireRequest",
	// 			}).Error("给公会积分失败")
	// 		} else {
	// 			utils.AsyncFunc(func() {
	// 				p.UpdateProp(req.GetType(), uProp)
	// 			})
	// 		}
	// 	}

	// 	p.DeleteData("fireUser")

	// 	if !tu.Robot {
	// 		tu.UnFire()

	// 		m.AddEventMsg(tu.Uid, &m.EventMsg{
	// 			Id:          bson.NewObjectId().Hex(),
	// 			Uid:         p.User.Uid.Hex(),
	// 			Name:        p.User.Name,
	// 			Head:        p.User.Head,
	// 			Op:          eventFireOp,
	// 			Time:        utils.TNow().Unix(),
	// 			AvatarFrame: p.User.AvatarFrame,
	// 		})

	// 		isProtec, _ := lib.CheckAllGridIsFire(tu)
	// 		if isProtec {
	// 			slot.AddProtec(tu.Uid.Hex(), slot.EndOverTime)
	// 		}

	// 		// 删除仇人
	// 		p.User.GetFoe().DelMember(tu.Uid.Hex())
	// 		// 添加仇人
	// 		tu.GetFoe().AddMember(p.User.Uid.Hex())
	// 	}

	// 	p.PutData("slotKey", int64(0))
	// 	res = &sp.SlotFireResponse{
	// 		Errcode: errcode,
	// 		Reward:  lib.FormatGoodsInfoSp(resGoods),
	// 	}
	// 	utils.AsyncFunc(func() {
	// 		p.UpdateProp(req.GetType(), uProp)
	// 	})
	// 	return res, nil
	// }
	return
}

//放火事件 选择在线的玩家
func (p *Player) SlotFireOnReqRequest(req *sp.SlotFireOnReqRequest) (res *sp.SlotFireOnReqResponse, err error) {
	us := p.User
	uid := us.Uid.Hex()

	res = &sp.SlotFireOnReqResponse{
		Errcode: data.Errcode.ServerErr,
	}
	slotKey, ok := p.GetData("slotKey")
	if !ok {
		res = &sp.SlotFireOnReqResponse{
			Errcode: data.Errcode.ServerErr,
		}
		log.WithFields(log.Fields{
			"uid":    uid,
			"method": "SlotFireOnReqRequest",
		}).Error("没有获取到任何事件")
		return
	}

	if slotKey.(int64) != 666 {
		res = &sp.SlotFireOnReqResponse{
			Errcode: data.Errcode.ServerErr,
		}
		log.WithFields(log.Fields{
			"data":   map[string]interface{}{"slotKey": slotKey},
			"uid":    uid,
			"method": "SlotFireOnReqRequest",
		}).Error("不是放火事件")
		return
	}
	p.PutData("slotFireEndTime", utils.TNow().Add(5*time.Minute).Unix())

	// 新手引导
	newGuildFlag := false
	uNewGuide := p.User.GetNewGuide()
	// 新手引导
	if !uNewGuide.SlotFlag && p.User.MaxPos.LockBlockTid == 1 {
		newGuildFlag = true
	}

	var lockBlockTid int64 = 0
	if req.Uid == "" {
		// gm 设置被烧的玩家
		if v, ok := p.GetData("gmFireUserOn"); ok {
			p.DeleteData("gmFireUserOn")
			p.PutData("fireUser", v.(string))
			tuPlayer, ok := p.getPlayer(v)
			if !ok {
				log.WithFields(log.Fields{
					"uid":    us.Uid.Hex(),
					"method": "SlotFireOnReqRequest",
				}).Error("gmFireUserOn 没有找到被放火的玩家")
				return res, nil
			}
			// 玩家正在被放火，5分钟内，被禁
			// tuPlayer.User.FireIng()
			// 增加放火次数
			p.User.GetUserStatic().AddTypNum(data.StaticTYP.Fire, 1)
			lockBlockTid = tuPlayer.User.Pos.LockBlockTid
			// 移除被保护
			// slot.RemoveFireProtec(p.User.Uid.Hex())
			res = &sp.SlotFireOnReqResponse{
				FireInfo: &sp.SlotFireInfo{
					UserInfo:     lib.FormatSlotUser(p.User, tuPlayer.User, newGuildFlag),
					Layer:        lib.FormartLayerSp(tuPlayer.User.GetLayer()),
					UserPet:      lib.FormatPetSp(tuPlayer.User.GetUserPet().GetActivePet()),
					LockBlockTid: lockBlockTid,
				},
			}
			return res, nil
		}
		//新手玩家攻击
		if _, ok := p.GetData("newGuildFireShield"); ok {
			p.DeleteData("newGuildFireShield")
			robot, robotLayer, _ := lib.NewGuildRobot()
			p.PutData("fireUser", robot)
			p.PutData("robotLayer", robotLayer)
			res = &sp.SlotFireOnReqResponse{
				FireInfo: &sp.SlotFireInfo{
					UserInfo: lib.FormatSlotUser(us, robot, newGuildFlag),
					Layer:    lib.FormartLayerSp(robotLayer),
				},
			}
			return res, nil
		}

		// 匹配好友
		lst := lib.GetFriendsUidLst(us)
		tuid, ok := slot_fire.MatchFireUserLst(us, lst)
		if !ok {
			// 匹配工会玩家
			lst = union.UnionModule.UnionMemberUidList(p.User.UnionId)
			tuid, ok = slot_fire.MatchFireUserLst(us, lst)
			if !ok {
				// 匹配普通玩家
				tuid, ok = slot_fire.MatchFireUser(us) //匹配被烧玩家
			}
		}

		// 老虎机匹配被攻击的玩家
		var pet *m.Pet = nil
		var layer *m.Layer
		var fireUser *m.User
		if ok {
			fireUser, _ = PlayersModule.GetUser(tuid)
			p.PutData("fireUser", fireUser.Uid.Hex())
			layer = fireUser.GetLayer()
			pet = fireUser.GetUserPet().GetActivePet()
			lockBlockTid = fireUser.Pos.LockBlockTid
			// fireUser.FireIng()
		} else {
			fireUser, _, layer, _ = lib.NewRobot()
			p.PutData("fireUser", fireUser)
			p.PutData("robotLayer", layer)
		}
		// 增加放火次数
		p.User.GetUserStatic().AddTypNum(data.StaticTYP.Fire, 1)
		// 移除被保护
		// slot.RemoveFireProtec(p.User.Uid.Hex())
		res = &sp.SlotFireOnReqResponse{
			FireInfo: &sp.SlotFireInfo{
				UserInfo:     lib.FormatSlotUser(p.User, fireUser, newGuildFlag),
				Layer:        lib.FormartLayerSp(layer),
				UserPet:      lib.FormatPetSp(pet),
				LockBlockTid: lockBlockTid,
			},
		}
		return res, nil
	}
	//放火玩家选择被烧玩家
	tuPlayer, ok := p.getPlayer(req.Uid)
	if !ok {
		log.WithFields(log.Fields{
			"uid":    p.User.Uid.Hex(),
			"method": "SlotFireOnReqRequest",
			"data":   req,
		}).Error("没有找到被放火的玩家")
		res = &sp.SlotFireOnReqResponse{
			Errcode: data.Errcode.ServerErr,
		}
		return res, nil
	}
	lockBlockTid = tuPlayer.User.Pos.LockBlockTid
	//更新被烧家ID
	p.PutData("fireUser", req.Uid)
	// 增加放火次数
	p.User.GetUserStatic().AddTypNum(data.StaticTYP.Fire, 1)
	// 移除被保护
	// slot.RemoveFireProtec(p.User.Uid.Hex())
	res = &sp.SlotFireOnReqResponse{
		FireInfo: &sp.SlotFireInfo{
			UserInfo:     lib.FormatSlotUser(p.User, tuPlayer.User, newGuildFlag),
			Layer:        lib.FormartLayerSp(tuPlayer.User.GetLayer()),
			UserPet:      lib.FormatPetSp(tuPlayer.User.GetUserPet().GetActivePet()),
			LockBlockTid: lockBlockTid,
		},
	}
	return
}

//放火 对在线玩家放火
func (p *Player) SlotFireOnRequest(req *sp.SlotFireOnRequest) (res *sp.SlotFireOnResponse, err error) {
	slotfireEndTime, ok := p.GetData("slotFireEndTime")
	if !ok {
		res = &sp.SlotFireOnResponse{
			Errcode: data.Errcode.ServerErr,
		}
		log.WithFields(log.Fields{
			"uid":    p.User.Uid.Hex(),
			"method": "SlotFireOnRequest",
		}).Error("没有获取到放火结束时间")
		return
	}
	if utils.TNow().Unix() > slotfireEndTime.(int64) {
		log.WithFields(log.Fields{
			"uid":    p.User.Uid.Hex(),
			"method": "SlotFireOnRequest",
		}).Debug("放火超时")
		res = &sp.SlotFireOnResponse{
			Errcode: data.Errcode.FireTimeOut,
		}
		return res, nil
	}

	if v, ok := p.GetData("fireUser"); ok {
		tuPlayer, ok := p.getPlayer(v)
		if !ok {
			res = &sp.SlotFireOnResponse{
				Errcode: data.Errcode.ServerErr,
			}
			log.WithFields(log.Fields{
				"uid":    p.User.Uid.Hex(),
				"data":   map[string]interface{}{"fireUser": v},
				"method": "SlotFireOnRequest",
			}).Error("未获取到放火玩家")
			return
		}
		tu := tuPlayer.User
		// tu.UnFire()

		if !tuPlayer.User.Robot {
			if tuPlayer.User.IsOnLine() {
				//通知被烧玩家
				utils.AsyncFunc(func() {
					tuPlayer.Send(&sp.SlotFireNoticeRequest{
						Uid:         p.User.Uid.Hex(),
						Name:        p.User.Name,
						Head:        p.User.Head,
						AvatarFrame: p.User.AvatarFrame,
					})
				})
			} else {

			}
		}

		spin, _ := p.GetData("slotSpin")
		var uProp, tuProp *m.UpdateProp
		var resGoods *m.Goods
		var err error
		if tu.Robot {
			val, _ := p.GetData("robotLayer")
			layer := val.(*m.Layer)
			uProp, resGoods, err = lib.RobotSlotFire("SlotFireOnRequest", p.User, tu, layer, req.GridIds, spin.(int64), p.Send)
		} else {
			// 楼层和关卡和玩家当前一致
			burn := req.LayerId == tu.Pos.LayerId && req.LockBlockTid == tu.Pos.LockBlockTid
			uProp, tuProp, resGoods, err = lib.SlotFireOn("SlotFireOnRequest", p.User, tu, req.GridIds, req.MidId, spin.(int64), burn, p.Send)
		}
		// 有委托完成
		if num := lib.EntrustCheck(p.User); num > 0 {
			utils.AsyncFunc(func() {
				p.Send(&sp.EntrustNoticeRequest{Num: num})
			})
		}

		var errcode int64 = 0
		var eventFireOp int64 = 2
		if err != nil {
			if errors.ErrCode(err) == data.Errcode.HasShield {
				errcode = data.Errcode.HasShield
				eventFireOp = 3
			} else if errors.ErrCode(err) == data.Errcode.HasPetSkillShield {
				errcode = data.Errcode.HasPetSkillShield
				eventFireOp = 4
			} else if errors.ErrCode(err) == data.Errcode.HasPetSkillDestroyShield {
				errcode = data.Errcode.HasPetSkillDestroyShield
			} else if errors.ErrCode(err) == data.Errcode.HasPetSkillDestroyShieldAndTriggerResist {
				errcode = data.Errcode.HasPetSkillDestroyShieldAndTriggerResist
				eventFireOp = 4
			} else {
				res = &sp.SlotFireOnResponse{
					Errcode: errors.ErrCode(err),
				}
				return res, err
			}
		}

		if p.User.UnionId != "" {
			uProp, _, _, err := lib.GiveGoodsByKv("SlotFireOnRequest", p.User, m.BaseKV{Key: data.GlobalEnum.Union, Val: spin.(int64)}, p.Send)
			if err != nil {
				log.WithFields(log.Fields{
					"data":   spin.(int64),
					"uid":    p.User.Uid.Hex(),
					"method": "SlotFireOnRequest",
				}).Error("给公会积分失败")
			} else {
				// 有成就完成，进行通知
				achLst := lib.AchievComplete(p.User)
				if len(achLst) > 0 {
					p.Send(&sp.AchievementNoticeRequest{
						Lst: achLst,
					})
				}
				p.TimelyUpdateProp(req.GetType(), uProp)
				utils.AsyncFunc(func() {
					p.UpdateProp(req.GetType(), uProp)
				})
			}
		}

		// 新手引导
		newGuildFlag := false
		uNewGuide := p.User.GetNewGuide()
		// 新手引导
		if !uNewGuide.SlotFlag && p.User.MaxPos.LockBlockTid == 1 {
			newGuildFlag = true
			uNewGuide.RewardCnt++
			uNewGuide.Update(uNewGuide)
		}
		// 触发老虎机活动--攻击行为
		if activity.ActivityModule.HasSlotAct() && newGuildFlag == false {
			if eventFireOp == 2 { // 攻击成功
				p.SlotActActionOccur(data.SlotActActionEnum.SucAtt, spin.(int64))
			} else { // 攻击失败
				p.SlotActActionOccur(data.SlotActActionEnum.FailAtt, spin.(int64))
			}
		}

		if !tu.Robot {
			//解除放火保护
			// tu.UnFire()
			//被烧玩家记录放火玩家，用于邮件提示。
			m.AddEventMsg(tu.Uid, &m.EventMsg{
				Id:          bson.NewObjectId().Hex(),
				Uid:         p.User.Uid.Hex(),
				Name:        p.User.Name,
				Head:        p.User.Head,
				Op:          eventFireOp,
				Time:        utils.TNow().Unix(),
				AvatarFrame: p.User.AvatarFrame,
			})
			// 没有格子放火，进行保护
			// if isProtec, _ := lib.CheckAllGridIsFire(tu); isProtec {
			// 	slot.AddFireProtec(tu.Uid.Hex(), slot.EndOverTime)
			// }
			// 删除仇人
			p.User.GetFoe().DelMember(tu.Uid.Hex())
			// 添加仇人
			tu.GetFoe().AddMember(p.User.Uid.Hex())
			if tu.IsOnLine() {
				//获取被攻击的格子信息
				gridList, _ := lib.GetGridInfoByIds(tu, req.GridIds)
				// 玩家在线 向被烧玩家反馈信息
				utils.AsyncFunc(func() {
					tuPlayer.Send(&sp.SlotFireMsgNoticeRequest{
						Errcode:      errcode,
						GridList:     lib.FormartGridInfoSps(gridList),
						LockBlockTid: tu.Pos.LockBlockTid,
						LayerId:      tu.Pos.LayerId,
						OpenGridNum:  tu.Pos.LayerOpenGridNum,
					})
				})
				if tuProp != nil {
					// 更新被攻击玩家信息，主要是扣盾信息
					tuPlayer.TimelyUpdateProp(req.GetType(), tuProp)
					utils.AsyncFunc(func() {
						tuPlayer.UpdateProp(req.GetType(), tuProp)
					})
				}
			}

			//被攻击玩家 在日志中 记录被攻击信息
			plog.Log_BeFireLog(tu, p.User.Uid.Hex(), tu.Pos, req.GridIds)
			// 删除放火使用
			slot_fire.RemoveFireUse(tu.Uid.Hex())
			// 被放火的玩家，保护5分钟
			slot_fire.AddFireProtec(tu.Uid.Hex(), utils.TNow().Add(5*time.Minute).Unix())
		}
		resGoo := make([]*m.Goods, 0)
		resGoo = append(resGoo, resGoods)
		//放火玩家 在日志中 记录放火信息
		plog.Log_FireLog(p.User, tu, tu.Robot, resGoo, uProp)

		p.PutData("slotKey", int64(0))
		res = &sp.SlotFireOnResponse{
			Errcode: errcode,
			Reward:  lib.FormatGoodsInfoSp(resGoods),
		}
		//更新玩家被修改的信息
		p.TimelyUpdateProp(req.GetType(), uProp)
		utils.AsyncFunc(func() {
			p.UpdateProp(req.GetType(), uProp)
		})
		return res, nil
	}

	log.WithFields(log.Fields{
		"data":   p.User.Uid.Hex(),
		"method": "SlotFireOnRequest",
	}).Error("放火没有找到slotUser")
	res = &sp.SlotFireOnResponse{
		Errcode: data.Errcode.ServerErr,
	}
	return
}

// 增加老虎机玩家
func (p *Player) AddSlotUser() (res_slotUser *sp.SimpleUser) {
	nowUnix := utils.TNow().Unix()
	p.PutData("richTime", nowUnix) // 大富豪更新时，重置大富豪起始时间
	uid := p.User.Uid.Hex()

	uNewGuide := p.User.GetNewGuide()
	// 新手引导
	newGuildFlag := false
	if !uNewGuide.SlotFlag && p.User.MaxPos.LockBlockTid == 1 {
		newGuildFlag = true
		robot, robotLayer, _ := lib.NewGuildRobot()
		p.PutData("slotUser", robot)
		p.PutData("robotLayer", robotLayer)
		return lib.FormatSlotUser(p.User, robot, newGuildFlag)
	}

	// 匹配好友
	lst := lib.GetFriendsUidLst(p.User)
	tuid, ok := slot_steal.MatchStealUserLst(uid, lst)
	if !ok {
		// 匹配工会玩家
		lst = union.UnionModule.UnionMemberUidList(p.User.UnionId)
		tuid, ok = slot_steal.MatchStealUserLst(uid, lst)
		if !ok {
			// 匹配普通玩家
			tuid, ok = slot_steal.MatchStealUser(uid)
		}
	}

	var slotUser *m.User
	var robotLayer *m.Layer
	if ok {
		slotUser, _ = PlayersModule.GetUser(tuid)
		p.PutData("slotUser", slotUser.Uid.Hex())
		slotUser.SetSlotNoticeUser(uid) // 大富豪绑定小偷
	} else {
		slotUser, _, robotLayer, _ = lib.NewRobot()
		p.PutData("slotUser", slotUser)
		p.PutData("robotLayer", robotLayer)
	}

	res_slotUser = lib.FormatSlotUser(p.User, slotUser, newGuildFlag)
	// p.TimelyUpdateProp(req.GetType(), uProp)
	p.UpdateProp(0, &sp.UpdatePropRequest{SlotUser: res_slotUser})
	return res_slotUser
}

// 移除被占用的老虎机玩家
// 老虎机匹配池新增被移除的该玩家
func (p *Player) RemoveSlotUser() {
	if v, ok := p.GetData("slotUser"); ok {
		switch v.(type) {
		case string:
			tuPlayer, _ := p.getPlayer(v)
			tuPlayer.User.SetSlotNoticeUser("") // 富豪和小偷解除绑定
			slot_steal.RemoveStealUse(v.(string))
			slot_steal.AddStealUser(v.(string))
		default:
		}
	}
}

// 刷新老虎机玩家
func (p *Player) RefreshSlotUser() {
	if v, ok := p.GetData("slotUser"); ok {
		_ = p.AddSlotUser() // 先增加
		switch v.(type) {
		case string:
			tuPlayer, _ := p.getPlayer(v)
			if tuPlayer.User.SlotNoticeUser == p.User.Uid.Hex() {
				tuPlayer.User.SetSlotNoticeUser("") // 富豪和小偷解除绑定
			}
			slot_steal.RemoveStealUse(v.(string))
			slot_steal.AddStealUser(v.(string))
		default:
		}
	}
}

func (p *Player) getPlayer(val interface{}) (r *Player, ok bool) {
	switch val.(type) {
	case string:
		return PlayersModule.GetPlayer(val.(string))
	case *m.User:
		r = NewPlayer()
		r.User = val.(*m.User)
		return r, true
	}
	return nil, false
}

// 金钱改变时老虎机匹配池受到影响
func (p *Player) GoldEffectSlotMatchPool() {
	// 金币小于25W的玩家，移除老虎机。
	if p.User.Gold < data.SlotLimitGold {
		if _, ok := p.GetData("slotGoldLess"); !ok {
			p.PutData("slotGoldLess", true)
			p.DeleteData("slotGoldOver")
			if p.User.SlotNoticeUser != "" { // 玩家被老虎机使用
				tuPlayer, ok := p.getPlayer(p.User.SlotNoticeUser) // 玩家被使用谁使用，需要更新他的大富豪。
				if ok && tuPlayer != nil {
					tuPlayer.RefreshSlotUser() // 更新关联的玩家的大富豪
				}
			}
			slot_steal.RemoveStealMatch(p.User.Uid.Hex())
		}
	} else {
		if _, ok := p.GetData("slotGoldOver"); !ok {
			p.PutData("slotGoldOver", true)
			slot_steal.AddStealUser(p.User.Uid.Hex())
			p.DeleteData("slotGoldLess")
		}
	}
}

// 玩家自身属性刷新通知老虎机玩家
func (p *Player) UpdateNoticeSlotUser() {
	if p.User.SlotNoticeUser == "" {
		return
	}
	tuPlayer, ok := p.getPlayer(p.User.SlotNoticeUser)
	if !ok {
		return
	}
	if tuPlayer == nil {
		return
	}

	uNewGuide := p.User.GetNewGuide()
	// 新手引导
	newGuildFlag := false
	if !uNewGuide.SlotFlag && p.User.MaxPos.LockBlockTid == 1 {
		newGuildFlag = true
	}
	// p.TimelyUpdateProp(req.GetType(), uProp)
	tuPlayer.UpdateProp(0, &sp.UpdatePropRequest{SlotUser: lib.FormatSlotUser(tuPlayer.User, p.User, newGuildFlag)})
	// tuPlayer.UpdateProp(0, &sp.UpdatePropRequest{})
}

// 获取放火仇人列表
func (p *Player) SlotFoeMemberRequest(req *sp.SlotFoeMemberRequest) (res *sp.SlotFoeMemberResponse) {
	foe := p.User.GetFoe()
	res = &sp.SlotFoeMemberResponse{
		Members: lib.FormatSlotFoeMemberSps(foe.Members),
	}
	return
}
